#include "PluginManager.h"
#include "Log.h"
#include "camera_factory_helper.h"

// 默认设置debug模式为false
bool DEBUG_ENABLE = false;
/**
 * debug开关
 * @param env
 * @param info
 * @return
 */
static napi_value nativeEnableDebug(napi_env env, napi_callback_info info) {
    napi_value args[1] = {0};
    size_t argc = 1;
    // 获取传递进来的值
    if (napi_get_cb_info(env, info, &argc, args, nullptr, nullptr) != napi_ok) {
        return napiUtils::createIntNapi(env, 0);
    }
    int debugStatus;
    if (!napiUtils::loadNapiInt(env, args[0], &debugStatus)) {
        return napiUtils::createIntNapi(env, 0);
    }
    DEBUG_ENABLE = debugStatus == 1;
    LOG_I("当前的debug状态:%{public}s", DEBUG_ENABLE ? "打开" : "关闭");
    return napiUtils::createIntNapi(env, 1);
}

static napi_value nativeOpenVideo(napi_env env, napi_callback_info info) {
    napi_value args[1] = {0};
    size_t argc = 1;
    // 获取传递进来的值
    if (napi_get_cb_info(env, info, &argc, args, nullptr, nullptr) != napi_ok) {
        return napiUtils::createIntNapi(env, 0);
    }
    auto videoPath = napiUtils::loadNapiString(env, args[0]);
    if (!videoPath) {
        return napiUtils::createIntNapi(env, 0);
    }
    auto factory = CameraFactoryHelper::openCamera(videoPath);
    SAFE_FREE(videoPath);
    if (factory) {
        return napiUtils::createLongNapi(env, reinterpret_cast<int64_t>(factory));
    }
    return nullptr;
}
static napi_value nativeOpen(napi_env env, napi_callback_info info) {
    napi_value args[3] = {0};
    size_t argc = 3;
    // 获取传递进来的值
    if (napi_get_cb_info(env, info, &argc, args, nullptr, nullptr) != napi_ok) {
        return napiUtils::createIntNapi(env, 0);
    }
    int32_t fd;
    int32_t busNum;
    int32_t devAddress;
    if (!napiUtils::loadNapiInt(env, args[0], &fd) || !napiUtils::loadNapiInt(env, args[1], &busNum) ||
        !napiUtils::loadNapiInt(env, args[2], &devAddress)) {
        return napiUtils::createIntNapi(env, 0);
    }
    auto factory = CameraFactoryHelper::openCamera(fd, busNum, devAddress);
    if (factory) {
        return napiUtils::createLongNapi(env, reinterpret_cast<int64_t>(factory));
    }
    return nullptr;
}

static napi_value nativeClose(napi_env env, napi_callback_info info) {
    napi_value napiValue = napiUtils::loadNapiArgs(env, info);
    if (!napiValue) {
        return napiUtils::createIntNapi(env, 0);
    }
    int64_t cameraId;
    if (!napiUtils::loadNapiLong(env, napiValue, &cameraId)) {
        return napiUtils::createIntNapi(env, 0);
    }
    bool result = CameraFactoryHelper::closeCamera(cameraId);
    return napiUtils::createIntNapi(env, result ? 1 : 0);
}

static napi_value nativeStartPreview(napi_env env, napi_callback_info info) {
    napi_value napiValue = napiUtils::loadNapiArgs(env, info);
    if (!napiValue) {
        return napiUtils::createIntNapi(env, 0);
    }
    int64_t cameraId;
    if (!napiUtils::loadNapiLong(env, napiValue, &cameraId)) {
        return napiUtils::createIntNapi(env, 0);
    }
    ICameraFactory *camera = reinterpret_cast<ICameraFactory *>(cameraId);
    if (camera) {
        bool ret = camera->startPreview();
        return napiUtils::createIntNapi(env, ret ? 1 : 0);
    }
    return napiUtils::createIntNapi(env, 0);
}

static napi_value nativeStopPreview(napi_env env, napi_callback_info info) {
    napi_value napiValue = napiUtils::loadNapiArgs(env, info);
    if (!napiValue) {
        return napiUtils::createIntNapi(env, 0);
    }
    int64_t cameraId;
    if (!napiUtils::loadNapiLong(env, napiValue, &cameraId)) {
        return napiUtils::createIntNapi(env, 0);
    }
    ICameraFactory *camera = reinterpret_cast<ICameraFactory *>(cameraId);
    if (camera) {
        bool ret = camera->stopPreview();
        return napiUtils::createIntNapi(env, ret ? 1 : 0);
    }
    return napiUtils::createIntNapi(env, 0);
}

static napi_value nativeSetPreviewSize(napi_env env, napi_callback_info info) {
    napi_value args[5] = {0};
    size_t argc = 5;
    // 获取传递进来的值

    if (napi_get_cb_info(env, info, &argc, args, nullptr, nullptr) != napi_ok) {
        return nullptr;
    }
    int64_t cameraId;
    if (!napiUtils::loadNapiLong(env, args[0], &cameraId)) {
        return napiUtils::createIntNapi(env, 0);
    }
    ICameraFactory *camera = reinterpret_cast<ICameraFactory *>(cameraId);

    int32_t width;
    int32_t height;
    int32_t format;
    if (!napiUtils::loadNapiInt(env, args[1], &width) || !napiUtils::loadNapiInt(env, args[2], &height) ||
        !napiUtils::loadNapiInt(env, args[3], &format)) {
        return napiUtils::createIntNapi(env, 0);
    }
    if (camera) {
        bool ret = camera->setPreviewSize(width, height, format);
        return napiUtils::createIntNapi(env, ret ? 1 : 0);
    }
    return napiUtils::createIntNapi(env, 0);
}

static napi_value nativeSetDisplaySurface(napi_env env, napi_callback_info info) {
    napi_value args[2] = {0};
    size_t argc = 2;
    // 获取传递进来的值

    if (napi_get_cb_info(env, info, &argc, args, nullptr, nullptr) != napi_ok) {
        return napiUtils::createIntNapi(env, 0);
    }
    int64_t cameraId;
    char *surfaceId = napiUtils::loadNapiString(env, args[1]);
    if (!napiUtils::loadNapiLong(env, args[0], &cameraId) || !surfaceId) {
        return napiUtils::createIntNapi(env, 0);
    }
    ICameraFactory *camera = reinterpret_cast<ICameraFactory *>(cameraId);
    if (camera) {
        bool ret = camera->setDisplaySurface(surfaceId);
        return napiUtils::createIntNapi(env, ret ? 1 : 0);
    }
    free_napi(surfaceId);
    return napiUtils::createIntNapi(env, 0);
}

static napi_value nativeSetPreviewListener(napi_env env, napi_callback_info info) {
    napi_value args[3] = {0};
    size_t argc = 3;
    // 获取传递进来的值

    if (napi_get_cb_info(env, info, &argc, args, nullptr, nullptr) != napi_ok) {
        return napiUtils::createIntNapi(env, 0);
    }
    int64_t cameraId;
    int32_t mode;
    if (!napiUtils::loadNapiLong(env, args[0], &cameraId) || !napiUtils::loadNapiInt(env, args[2], &mode)) {
        return napiUtils::createIntNapi(env, 0);
    }
    ICameraFactory *camera = reinterpret_cast<ICameraFactory *>(cameraId);
    if (camera) {
        camera->setPreviewDataListener(env, args[1], mode);
        return napiUtils::createIntNapi(env, 1);
    }
    return napiUtils::createIntNapi(env, 0);
}

static napi_value nativeGetParameterValue(napi_env env, napi_callback_info info) {
    napi_value args[2] = {0};
    size_t argc = 2;
    // 获取传递进来的值

    if (napi_get_cb_info(env, info, &argc, args, nullptr, nullptr) != napi_ok) {
        return nullptr;
    }
    int64_t cameraId;
    if (!napiUtils::loadNapiLong(env, args[0], &cameraId)) {
        return nullptr;
    }
    int type;
    if (!napiUtils::loadNapiInt(env, args[1], &type)) {
        return nullptr;
    }
    ICameraFactory *camera = reinterpret_cast<ICameraFactory *>(cameraId);
    if (camera) {
        auto result = camera->getParameter(type);
        if (std::holds_alternative<std::monostate>(result)) {
            return nullptr;
        } else if (std::holds_alternative<int>(result)) {
            return napiUtils::createIntNapi(env, std::get<int>(result));
        } else if (std::holds_alternative<std::string>(result)) {
            auto value = std::get<std::string>(result);
            LOG_D("当前获取到的值为:%{public}s", value.c_str());
            auto napiValue = napiUtils::createStringNapi(env, value.c_str());
            return napiValue;
        }
    }
    return nullptr;
}

static napi_value nativeSetParameterValue(napi_env env, napi_callback_info info) {
    napi_value args[3] = {0};
    size_t argc = 3;
    // 获取传递进来的值
    if (napi_get_cb_info(env, info, &argc, args, nullptr, nullptr) != napi_ok) {
        return napiUtils::createIntNapi(env, 0);
    }
    int64_t cameraId;
    if (!napiUtils::loadNapiLong(env, args[0], &cameraId)) {
        return napiUtils::createIntNapi(env, 0);
    }
    int type;
    int value;
    if (!napiUtils::loadNapiInt(env, args[1], &type) || !napiUtils::loadNapiInt(env, args[2], &value)) {
        return napiUtils::createIntNapi(env, 0);
    }
    ICameraFactory *camera = reinterpret_cast<ICameraFactory *>(cameraId);
    if (camera) {
        bool ret = camera->setParameter(type, value);
        return napiUtils::createIntNapi(env, ret ? 1 : 0);
    }
    return napiUtils::createIntNapi(env, 0);
}

static napi_value nativeGetSupportedParameters(napi_env env, napi_callback_info info) {
    napi_value args[2] = {0};
    size_t argc = 2;
    // 获取传递进来的值
    if (napi_get_cb_info(env, info, &argc, args, nullptr, nullptr) != napi_ok) {
        return nullptr;
    }
    int64_t cameraId;
    int type;
    if (!napiUtils::loadNapiLong(env, args[0], &cameraId) || !napiUtils::loadNapiInt(env, args[1], &type)) {
        return nullptr;
    }
    ICameraFactory *camera = reinterpret_cast<ICameraFactory *>(cameraId);
    if (camera) {
        auto result = camera->getSupportParameters(type);
        if (std::holds_alternative<std::monostate>(result)) {
            return nullptr;
        } else if (std::holds_alternative<int>(result)) {
            return napiUtils::createIntNapi(env, std::get<int>(result));
        } else if (std::holds_alternative<std::string>(result)) {
            LOG_I("获取到了char类型");
            auto value = std::get<std::string>(result);
            LOG_I("当前获取到的值为:%{public}s", value.c_str());
            if (value.empty()) {
                return nullptr;
            }
            return napiUtils::createStringNapi(env, value.c_str());
        } else if (std::holds_alternative<std::pair<int, int>>(result)) {
            auto value = std::get<std::pair<int, int>>(result);
            napi_value start = napiUtils::createIntNapi(env, value.first);
            napi_value end = napiUtils::createIntNapi(env, value.second);
            if (start == nullptr || end == nullptr) {
                return nullptr;
            }
            napi_value arrayValue = napiUtils::createArrayNapi(env, 2);
            if (arrayValue == nullptr) {
                return nullptr;
            }
            napi_set_element(env, arrayValue, 0, start);
            napi_set_element(env, arrayValue, 1, end);
            return arrayValue;
        }
    }
    return nullptr;
}

EXTERN_C_START static napi_value Init(napi_env env, napi_value exports) {
    napi_property_descriptor desc[] = {
        // 方法描述列表
        {"nativeEnableDebug", nullptr, nativeEnableDebug, nullptr, nullptr, nullptr, napi_default, nullptr},
        {"nativeOpen", nullptr, nativeOpen, nullptr, nullptr, nullptr, napi_default, nullptr},
        {"nativeOpenVideo", nullptr, nativeOpenVideo, nullptr, nullptr, nullptr, napi_default, nullptr},
        {"nativeClose", nullptr, nativeClose, nullptr, nullptr, nullptr, napi_default, nullptr},
        {"nativeStartPreview", nullptr, nativeStartPreview, nullptr, nullptr, nullptr, napi_default, nullptr},
        {"nativeStopPreview", nullptr, nativeStopPreview, nullptr, nullptr, nullptr, napi_default, nullptr},
        {"nativeSetDisplaySurface", nullptr, nativeSetDisplaySurface, nullptr, nullptr, nullptr, napi_default, nullptr},

        {"nativeSetPreviewSize", nullptr, nativeSetPreviewSize, nullptr, nullptr, nullptr, napi_default, nullptr},
        {"nativeGetParameterValue", nullptr, nativeGetParameterValue, nullptr, nullptr, nullptr, napi_default, nullptr},
        {"nativeSetParameterValue", nullptr, nativeSetParameterValue, nullptr, nullptr, nullptr, napi_default, nullptr},
        {"nativeGetSupportedParameters", nullptr, nativeGetSupportedParameters, nullptr, nullptr, nullptr, napi_default,
         nullptr},
        {"nativeSetPreviewListener", nullptr, nativeSetPreviewListener, nullptr, nullptr, nullptr, napi_default,
         nullptr},
    };
    LOG_I("HomeNavigation native Init");
    napi_status status = napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc);
    LOG_I("HomeNavigation native status:%{public}d", status == napi_ok);
    if (status != napi_ok) {
        return nullptr;
    }
    //    开始读取传入的surface数据
    PluginManager::GetInstance()->Export(env, exports);
    return exports;
}
EXTERN_C_END


// 模块配置
static napi_module uvc_cameraModule = {
    .nm_version = 1,
    .nm_flags = 0,
    .nm_filename = nullptr,
    .nm_register_func = Init,
    .nm_modname = "uvc_camera",
    .nm_priv = ((void *)0),
    .reserved = {0},
};
extern "C" __attribute__((constructor)) void RegisterUvc_cameraModule(void) {
    napi_module_register(&uvc_cameraModule); // 注册模块
}
